package com.smartplatform.service.impl;

import com.smartplatform.constants.ResultCode;
import com.smartplatform.dto.UserDto;
import com.smartplatform.event.LoginEvent;
import com.smartplatform.exception.AddDateException;
import com.smartplatform.exception.QueryException;
import com.smartplatform.mapper.SysUserMapper;
import com.smartplatform.pojo.CheckType;
import com.smartplatform.pojo.MyBaseUser;
import com.smartplatform.pojo.SysUserInfo;
import com.smartplatform.service.SysUserService;
import com.smartplatform.utils.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.Date;

/**
 * @Author 咕唧
 * @Date 2022/5/26 12:58
 * @Version 1.0
 */
@Service
@Transactional
public class SysUserServiceImpl implements SysUserService {

    private SysUserMapper sysUserMapper;
    private ApplicationContext context;
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    @Autowired
    public void setSysUserMapper(SysUserMapper sysUserMapper) {
        this.sysUserMapper = sysUserMapper;
    }

    @Override
    public void addUser(UserDto userDto) {
        //校验数据
        Assert.isTrue(!userDto.isEmpty(CheckType.ADD), () -> {
            throw new AddDateException("必要数据为空", ResultCode.DATA_NULL);
        });
        //判断注册用户是否存在,根据姓名，邮箱，手机号查询
        SysUserInfo userInfo = sysUserMapper.findByName(userDto.getUsername());
        Assert.isNull(userInfo, () -> {
            throw new AddDateException("用户已存在", ResultCode.USER_DATA_ERROR);
        });
        userInfo = sysUserMapper.findByEmail(userDto.getEmail());
        Assert.isNull(userInfo, () -> {
            throw new AddDateException("邮箱已存在", ResultCode.USER_DATA_ERROR);
        });
        Assert.isTrue(userInfo.getEmail().matches("/^([A-Za-z0-9_\\-\\.])+\\@([A-Za-z0-9_\\-\\.])+\\.([A-Za-z]{2,4})$/"), () -> {
            throw new AddDateException("邮箱格式不正确", ResultCode.USER_DATA_ERROR);
        });
        userInfo = sysUserMapper.findByPhone(userDto.getPhone());
        Assert.isNull(userInfo, () -> {
            throw new AddDateException("电话已存在", ResultCode.USER_DATA_ERROR);
        });
        Assert.isTrue(userInfo.getPhone().matches("^(13|15|18)\\d{9}$"), () -> {
            throw new AddDateException("电话号码格式不正确", ResultCode.USER_DATA_ERROR);
        });
        //密码长度必须大于六
        Assert.isTrue(userInfo.getPassword().trim().length() > 6, () -> {
            throw new AddDateException("电话号码格式不正确", ResultCode.USER_DATA_ERROR);
        });
        //System.out.println(sysUserInfo);
        //设置密码，密码加密
//        String salt = MyStringUtils.createRandom(10);
//        //把用户密码和生成的随机数一起加密
//        String md5PWD = DigestUtils.md5DigestAsHex((userDto.getPassword() + salt).getBytes());
//        //设置新密码
//        userDto.setPassword(md5PWD);
//        System.out.println(userDto.toString());
        //更新符合security的 注册密码生成方式
        userDto.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword()));
        //添加其他数据
        SysUserInfo sysUserInfo = new SysUserInfo();
        BeanUtils.copyProperties(userDto, sysUserInfo);
        //把盐保存到哦数据库
//        sysUserInfo.setPwdSalt(salt);
        //设置注册时间
        sysUserInfo.setCreateTime(new Date());
        //设置状态 是不是删除 封禁等
        sysUserInfo.setStatus(1L);
        //用户类型,普通用户等等
        sysUserInfo.setType(1L);
        sysUserInfo.setRemark("普通用户");
        sysUserInfo.setCreateBy(userDto.getUsername());
        System.out.println(sysUserInfo);
        sysUserMapper.addUser(sysUserInfo);
    }

    @Override
    public SysUserInfo login(UserDto userDto) {
        //判断传递的账号和密码是否为空
        Assert.isTrue(StringUtils.hasText(userDto.getUsername()) && StringUtils.hasText(userDto.getPassword()), () -> {
            throw new QueryException("必要数据为空", ResultCode.DATA_NULL);
        });
        //查询用户名是否存在
        SysUserInfo userInfo = sysUserMapper.findByName(userDto.getUsername());
        Assert.notNull(userInfo, () -> {
            //发送登录事假
            context.publishEvent(new LoginEvent(LoginEvent.LoginType.FAIL, userDto.getUsername()));
            throw new QueryException("用户名或密码不正确", ResultCode.USER_ERROR);
        });
        //判断用户密码是否正确
        String password = userInfo.getPassword();
        //接收用户的密码加密和数据库中的密码进行判断
        String md5Password = DigestUtils.md5DigestAsHex((userDto.getPassword() + userInfo.getPwdSalt()).getBytes());
        Assert.isTrue(password.equals(md5Password), () -> {
            context.publishEvent(new LoginEvent(LoginEvent.LoginType.FAIL, userDto.getUsername()));
            throw new QueryException("用户名或密码不正确", ResultCode.USER_ERROR);
        });
        //发送登录成功的事件
        context.publishEvent(new LoginEvent(LoginEvent.LoginType.SUCCESS, userDto.getUsername()));
        return userInfo;
    }

    @Override
    public void updateLogin(String username, Date processDate, String ip) {
        sysUserMapper.updateLogin(username, processDate, ip);
    }

    @Override
    public void modify(UserDto userDto) {
        //校验数据
        //必须要先确认密码才能修改
        Assert.hasText(userDto.getPassword(), ()->{
            throw new QueryException("必须要填写密码", ResultCode.DATA_NULL);
        });
        //获取登录用户的信息,检查输入密码和登录密码是否相同
        MyBaseUser sysUserInfo = SecurityUtils.getUserInfo(false);
        Assert.isTrue(bCryptPasswordEncoder.matches(userDto.getPassword(), sysUserInfo.getPassword()) , ()->{
            throw new QueryException("用户名或密码不正确", ResultCode.USER_ERROR);
        });
        //至少有一个数据不为空才修改
        Assert.isTrue(!userDto.isEmpty(CheckType.ADD), () -> {
            throw new AddDateException("缺少可修改项", ResultCode.DATA_NULL);
        });
        SysUserInfo userInfo=new SysUserInfo();
        BeanUtils.copyProperties(userDto, userInfo);
        System.err.println(userInfo);
        sysUserMapper.updateUser(userInfo);
    }

    /**
     * 查看用户个人信息，只能查看自己的信息，并且并不是所有的数据都能够给用户展示
     * @return
     */
    @Override
    public UserDto selectUser() {
        //获取登录用户的姓名
        MyBaseUser sysUserInfo = SecurityUtils.getUserInfo(false);
        //根据用户id查询
        return sysUserMapper.selectUserDto(sysUserInfo.getUserId());
    }

}
